package com.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import org.apache.log4j.Logger;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.web.jsf.FacesContextUtils;

import com.builder.SeccionBuilder;
import com.dao.BaseModelDAO;
import com.model.Seccion;
import com.query.SeccionQuery;
import com.util.JSFUtil;
import com.util.ValidatorUtil;
import com.view.SeccionView;

@ManagedBean
@ViewScoped
@SuppressWarnings("serial")
public class SeccionController extends PaginableController<Seccion> {

	private Logger log = Logger.getLogger(SeccionController.class);
	private BaseModelDAO<Seccion> dao;
	private Seccion model;
	private SeccionQuery query;
	private List<SelectItem> seccionSIL;

	@ManagedProperty("#{seccionView}")
	private SeccionView view;

	@ManagedProperty("#{seccionBuilder}")
	private SeccionBuilder builder;

	@SuppressWarnings("unchecked")
	public SeccionController() {

		try {
			dao = (BaseModelDAO<Seccion>) FacesContextUtils
					.getWebApplicationContext(FacesContext.getCurrentInstance())
					.getBean("seccionDAO");
			query = new SeccionQuery();
			actualizarSecciones();

			addEdit = false;

		} catch (Throwable e) {
			log.error("Error al inicializar la clase SeccionController", e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR,
							"Error al realizar la operacion", ""));
		}
	}

	private void actualizarSecciones() {
		seccionSIL = new ArrayList<SelectItem>();
		for (Seccion seccion : dao.getList()) {
			seccionSIL
					.add(new SelectItem(seccion.getID(), seccion.getNombre()));
		}
	}

	public SeccionQuery getQuery() {
		return query;
	}

	public void setQuery(SeccionQuery query) {
		this.query = query;
	}

	public Seccion getModel() {
		return model;
	}

	public void setModel(Seccion model) {
		this.model = model;
	}

	public SeccionView getView() {
		return view;
	}

	public void setView(SeccionView view) {
		this.view = view;
	}

	public SeccionBuilder getBuilder() {
		return builder;
	}

	public void setBuilder(SeccionBuilder builder) {
		this.builder = builder;
	}

	public List<SelectItem> getSeccionSIL() {
		return seccionSIL;
	}

	@Override
	public void query(ActionEvent event) {
		loadList();
	}

	@Override
	public void edit(ActionEvent event) {

		try {
			model = lazyDM.getRowData();
			view = builder.toView(model);
			addEdit = true;
		} catch (Throwable e) {
			log.error("Error al editar", e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR,
							"Error al realizar la operacion", ""));
		}

	}

	@Override
	public void delete(ActionEvent event) {

		try {
			model = lazyDM.getRowData();
			dao.delete(model);
			actualizarSecciones();
			loadList();
		} catch (DataIntegrityViolationException e) {
			JSFUtil.saveMessage(
					"El elemento no puede ser eliminado por estar relacionado con otro elemento del sistema.",
					FacesMessage.SEVERITY_ERROR);
		} catch (Throwable e) {
			log.error("Error al eliminar", e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR,
							"Error al realizar la operacion", ""));
		}
	}

	@Override
	public void add(ActionEvent event) {
		clear();
		actualizarSecciones();
		addEdit = true;
	}

	@Override
	public void save(ActionEvent event) {

		try {
			model = builder.toDomain(view);

			List<String> errores = new ValidatorUtil().validate(view);

			if (errores.size() == 0) {

				if (model.getID() != null) {
					dao.edit(model);
					addEdit = false;
				} else {
					dao.save(model);
				}
				actualizarSecciones();
				clear();
				JSFUtil.saveMessage("Elemento guardado con exito",
						FacesMessage.SEVERITY_INFO);
				if (!addEdit) {
					loadList();
				}

			} else {
				JSFUtil.saveMessages(errores);
			}

		} catch (Throwable e) {
			log.error("Error al guardar", e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR,
							"Error al realizar la operacion", ""));
		}
	}

	@Override
	public void cancel(ActionEvent event) {
		addEdit = false;
		lazyDM = null;
		clear();
	}

	@Override
	public void clear() {
		view = new SeccionView();
		view.setPadre(new SeccionView());
		model = new Seccion();
	}

	private void loadList() {

		lazyDM = new LazyDataModel<Seccion>() {
			@Override
			public List<Seccion> load(int first, int pageSize,
					String sortField, SortOrder sortOrder,
					Map<String, Object> filters) {

				Map<String, Object> filtro = new HashMap<String, Object>();
				filtro.put("nombre", query.getNombre());

				return dao.getList(first, pageSize, "nombre", true, filtro,
						true);
			}
		};

		Map<String, Object> filtro = new HashMap<String, Object>();
		filtro.put("nombre", query.getNombre());
		lazyDM.setRowCount(dao.count(filtro, true).intValue());
	}

}
